<template>
  <ul class="list" ref="list">
    <li class="item"
      v-for="letter in letters"
      :key="letter"
      :ref="letter"
      @click="handleLetterClick"
      @touchstart="handleTouchStart"
      @touchmove="handleTouchMove"
      @touchend="handleTouchEnd">
      {{ letter }}
    </li>
  </ul>
</template>

<script>
import MutationTypes from '@/store/MutationTypes'
import { mapMutations } from 'vuex'
export default {
  name: 'CityAlphabet',
  props: {
    cities: Object
  },
  data () {
    return {
      touchStatus: false,
      startY: 0,
      letterElementHeight: 0,
      timer: null
    }
  },
  computed: {
    letters () {
      return Object.keys(this.cities)
    }
  },
  methods: {
    handleLetterClick (event) {
      this.changeLetter({
        letter: event.target.innerText
      })
    },
    ...mapMutations({
      // 将 this.changeLetter() 映射为 this.$store.commit(MutationTypes.CHANGE_LETTER)
      changeLetter: MutationTypes.CHANGE_LETTER
    }),
    handleTouchStart () {
      this.touchStatus = true
    },
    handleTouchMove (e) {
      if (this.touchStatus) {
        // 在滚动时进行节流，提升性能
        if (this.timer) {
          clearTimeout(this.timer)
        }
        this.timer = setTimeout(() => {
          // 获取当前滑动事件所在字母离视口顶部的值
          const touchY = e.touches[0].clientY
          // 获取字母表每个字母距离对应的索引
          const index = ~~((touchY - this.startY) / this.letterElementHeight)
          // 在合适的时机修改 store 内的源数据
          if (index >= 0 && index < this.letters.length) {
            this.changeLetter({
              letter: this.letters[index]
            })
          }
        }, 16)
      }
    },
    handleTouchEnd () {
      this.touchStatus = false
    }
  },
  // 由于数据更改导致的虚拟 DOM 重新渲染和打补丁，在这之后会调用该钩子
  // https://cn.vuejs.org/v2/api/#updated
  updated () {
    // 获取字母表第一个字母即字母 'A' 的 DOM 实例
    const startElement = this.$refs['A'][0]
    // 获取该元素距离视口顶部的值
    const startY = startElement.getBoundingClientRect().top
    // 获取字母元素的高度
    const letterElementHeight = startElement.offsetHeight
    // 保存起始位置和字母元素高度信息，提升性能
    this.startY = startY
    this.letterElementHeight = letterElementHeight
  }
}
</script>

<style lang="stylus" scoped>
  @import '~styles/variables.styl'
  .list
    z-index 2
    display flex
    flex-direction column
    justify-content center
    position fixed
    top .88rem
    bottom 0
    right 0
    color $bgColor
    .item
      width .6rem
      height .4rem
      line-height .4rem
      text-align center
</style>
